 .INCLUDE "[FC][Mapper][Config].asm"
 
;CHR图形数据
;======================================================================
 .BANK NES_16KB_PRG_SIZE * 2
 .INCBIN "chr_bank/chr_data.chr"
 
 .BANK PROGRAM_BANK & BANK_DATA_MASK
 .ORG PROGRAM_ADDR
 
;--------------------------------------------------
Attributes_Data
;命名表属性
 .DB $00,$00,$00,$00,$00,$00,$00,$00,$55,$55,$55,$55,$55,$55,$55,$55
 .DB $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55
 .DB $55,$F5,$F5,$F5,$F5,$F5,$F5,$55,$55,$FF,$FF,$FF,$FF,$FF,$FF,$75
 .DB $A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
;--------------------------------------------------
;调色板数据
Palette_Data
 .DB $0F,$27,$20,$0F,$0F,$23,$20,$0F,$0F,$21,$20,$0F,$0F,$24,$20,$0F
 .DB $0F,$21,$24,$25,$0F,$24,$20,$0F,$0F,$24,$20,$0F,$0F,$24,$20,$0F

;--------------------------------------------------
;命名表文本索引
Name_Table_Text_Index
 .DW .Name_Table_Text_Data_1
 .DW .Name_Table_Text_Data_2
 .DW .Name_Table_Text_Data_3
 .DW .Name_Table_Text_Data_4
 .DW .Name_Table_Text_Data_5
 .DW $00;结束标记

.Name_Table_Text_Data_1
 .DB $20,$48
 .STR "MAPPER IRQ TEST"

.Name_Table_Text_Data_2
 .DB $22,$28
 .STR "SCROLL RIGHT"

.Name_Table_Text_Data_3
 .DB $22,$68
 .STR "SCROLL LEFT"

.Name_Table_Text_Data_4
 .DB $23,$26
 .STR "MADE BY FLAMECYCLONE"
 
.Name_Table_Text_Data_5
 .DB $23,$6B
 .STR "2023.12.01"
 
;==================================================
;命名表初始化
Init_Name_Table
 LDA #$20
 STA PPU_ADDRESS
 LDA #$00
 STA PPU_ADDRESS
 LDA #$00
 LDY #$00
 LDX #$10
Init_Name_Table_Write
 STA PPU_DATA
 INY
 BNE Init_Name_Table_Write
 DEX
 BNE Init_Name_Table_Write
 RTS
 
;==================================================
;调色板初始化
Init_Palette
 BIT PPU_STATUS
 LDA #$3F
 STA PPU_ADDRESS
 LDA #$00
 STA PPU_ADDRESS
 LDX #$00
Init_Palette_Write
 LDA Palette_Data,X
 STA PPU_DATA
 INX
 CPX #$20
 BCC Init_Palette_Write
 RTS
 
;==================================================
;设置命名表属性
Init_NameTable_Attributes
 BIT PPU_STATUS
 LDA #$23
 STA PPU_ADDRESS
 LDA #$C0
 STA PPU_ADDRESS
 LDX #$00
Init_NameTable_Attributes_Write
 LDA Attributes_Data,X
 STA PPU_DATA
 INX
 CPX #$40
 BCC Init_NameTable_Attributes_Write
 RTS

;==================================================
;初始化命名表文本
Init_Name_Table_Text
 BIT PPU_STATUS
 BIT $FFFF
 
 LDA #$00
 STA <FC_Data_Index

;检查需要写入的文本条目
.Write_Text_Begin
 LDA <FC_Data_Index
 ASL A
 TAY
 LDA Name_Table_Text_Index,Y
 STA <FC_Data_L
 INY
 LDA Name_Table_Text_Index,Y
 STA <FC_Data_H
 
 ;没有文本索引则结束
 LDA <FC_Data_L
 ORA <FC_Data_H
 BEQ .End
 JSR .Write_Text_Data
 INC <FC_Data_Index
 JMP .Write_Text_Begin
 
.End
 RTS

;读取文本数据位置和长度
.Write_Text_Data
 LDY #$00
 LDA [FC_Data_L],Y
 STA PPU_ADDRESS
 INY
 LDA [FC_Data_L],Y
 STA PPU_ADDRESS
 INY
 LDA [FC_Data_L],Y
 TAX
 INY
;写入PPU数据
.Write_PPU_Data
 LDA [FC_Data_L],Y
 STA PPU_DATA
 INY
 DEX
 BNE .Write_PPU_Data
 RTS

;==============================
Init_OAM_Ram;初始化精灵内存
 LDX #$00
 LDA #$00
 STA PPU_OAM_ADDR
 LDA #$F8
Init_OAM_Ram_Write
 STA PPU_OAM_DATA
 INX
 BNE Init_OAM_Ram_Write
 RTS
 
GamepadProcess;手柄处理
 JSR GamepadDatacan
 LDA <Gamepad_0_Value
 STA <Gamepad_0_State
 LDA <Gamepad_1_Value
 STA <Gamepad_1_State
 JSR GamepadDatacan
 LDX #$01
GamepadMergeCheck;合并手柄输入检查
 LDA <Gamepad_0_Value,X
 CMP <Gamepad_0_State,X
 BEQ GamepadMergeInput
 LDA <Gamepad_Temp,X
 STA <Gamepad_0_Value,X
GamepadMergeInput;合并手柄输入
 DEX
 BPL GamepadMergeCheck
 LDA <Gamepad_Merge
 AND #GAMEPAD_MERGE_FLAG
 BNE GamepadStateProcess
 LDA <Gamepad_0_Value
 ORA <Gamepad_1_Value
 STA <Gamepad_0_Value
GamepadStateProcess;手柄状态处理
 LDX #$01
GamepadStateSave;手柄状态保存
 LDA <Gamepad_0_Value,X
 TAY
 EOR <Gamepad_Temp,X
 AND <Gamepad_0_Value,X
 STA <Gamepad_Once,X
 STY <Gamepad_Keep,X
 STY <Gamepad_Temp,X
 DEX
 BPL GamepadStateSave
 RTS

GamepadDatacan;手柄数据扫描
 LDX #$01
 STX $4016
 DEX
 STX $4016
 LDY #$08
GamepadPortScan;手柄端口扫描
 LDA $4016
 STA <Gamepad_Port_Value
 LSR A
 ORA <Gamepad_Port_Value
 LSR A
 ROL <Gamepad_0_Value
 LDA $4017
 STA <Gamepad_Port_Value
 LSR A
 ORA <Gamepad_Port_Value
 LSR A
 ROL <Gamepad_1_Value
 DEY
 BNE GamepadPortScan
 RTS
 
;==================================================
;PPU处理, 这里仅重置PPU滚动
PPU_Process
 LDA #$00
 STA PPU_MASK
 
 BIT PPU_STATUS
 LDA #$20
 STA PPU_ADDRESS
 LDA #$00
 STA PPU_ADDRESS
 
 STA PPU_SCROLL
 STA PPU_SCROLL
 
 LDA PPU_Msak_Buf
 STA PPU_MASK

 RTS
 
;==============================
Time_For_Vblank;延时等待
 LDA PPU_STATUS
 BPL Time_For_Vblank
 RTS
 
;==================================================
;重置中断处理
ResetProgram
 SEI
 CLD
 LDA #$00
 STA PPU_CTRL
 STA PPU_MASK
 STA PPU_STATUS
 STA JOY2_FRAME
 STA APU_STATUS
 
 LDA #$C0
 STA JOY2_FRAME
 
;等待vblank
 LDX #$02
Vblank_Wait_1
 BIT PPU_STATUS
 BPL Vblank_Wait_1
Vblank_Wait_2
 BIT PPU_STATUS
 BMI Vblank_Wait_2
 DEX
 BNE Vblank_Wait_1
 
 LDX #$FF
 TXS
 
 ;初始化Mapper
 MACRO_MAPPER_INIT
 
;==============================
;RAM初始化
Nes_Ram_Init
 LDY #$00
 LDX #$08
 LDA #$00
 STA <$00
 STA <$01
Nes_Ram_Init_Write
 STA [$00],Y
 INY
 BNE Nes_Ram_Init_Write
 INC <$01
 DEX
 BNE Nes_Ram_Init_Write
  
 ;初始化命名表
 JSR Init_Name_Table
 
 ;初始化调色板
 JSR Init_Palette
 
 ;初始化命名表属性
 JSR Init_NameTable_Attributes
 
 ;初始化精灵内存
 JSR Init_OAM_Ram
 
 ;在屏幕上写点东西
 JSR Init_Name_Table_Text
 
 JSR Time_For_Vblank
 ;开启PPU控制
 LDA #$A8
 STA PPU_Ctrl_Buf
 STA PPU_CTRL
 
 ;开启PPU显示
 LDA #$1E
 STA PPU_Msak_Buf
 
 CLI
 JMP Loop
 
;==============================
;死循环, 等待NMI中断
Loop
 JMP Loop
 
;IRQ宏代码定义
 MACRO_IRQ_OPERATE

;==================================================
;NMI中断处理
NmiProgram
 PHA
 TXA
 PHA
 TYA
 PHA
 
 ;读取清除Vblank标志, 防止重复进入
 BIT PPU_STATUS
 
 ;水平滚动值增加
 INC Scroll_H
 
 ;启动IRQ
 MACRO_TRIGGER_FIRST_IRQ
 
 ;重置IRQ索引
 LDA #$00
 STA <IRQ_Process_Index
 
 ;关闭PPU控制
 LDA #$00
 STA PPU_CTRL
 
 ;处理PPU
 JSR PPU_Process
 
 ;开启PPU控制
 LDA PPU_Ctrl_Buf
 STA PPU_CTRL
 
 ;手柄处理
 JSR GamepadProcess
 
 PLA
 TAY
 PLA
 TAX
 PLA
 RTI

;==================================================
;IRQ中断处理
IrqProgram
 PHA
 TXA
 PHA
 TYA
 PHA
 
 ;IRQ确认
 MACRO_ACK_IRQ
 
 ;IRQ处理
 JSR IRQ_Process_By_Index
 
IrqProgramEnd
 PLA
 TAY
 PLA
 TAX
 PLA
 RTI
 
;==================================================
;中断表
 .ORG $FFFA
 .WORD NmiProgram
 .WORD ResetProgram
 .WORD IrqProgram